package com.qx.chat.akka.actor;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Order;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.web.socket.WebSocketSession;

import com.alibaba.fastjson.JSONObject;
import com.qx.chat.akka.Qxchat;
import com.qx.chat.system.dao.AbstractRepository;
import com.qx.chat.system.dao.ChatRecordDaoImpl;
import com.qx.chat.system.dao.GroupUserDaoImpl;
import com.qx.chat.system.dao.UserDaoImpl;
import com.qx.chat.system.entity.ChatMessageRecord;
import com.qx.chat.system.entity.GroupUser;
import com.qx.chat.system.entity.User;
import com.qx.chat.system.event.BandEvent.BandEditEvent;
import com.qx.chat.system.event.Event;
import com.qx.chat.system.event.GroupEvent.GroupEditEvent;
import com.qx.chat.system.event.SessionEvent;
import com.qx.chat.system.event.UserEvent;
import com.qx.chat.system.event.UserEvent.Firends;
import com.qx.chat.system.event.UserEvent.Login;
import com.qx.chat.system.event.UserEvent.SessionOpen;
import com.qx.chat.system.event.UserEvent.Status;
import com.qx.chat.system.message.Data;
import com.qx.chat.system.message.Message;
import com.qx.chat.system.message.TextMessage;
import com.qx.chat.system.service.ChatRecordService;
import com.qx.chat.system.service.ChatRecordServiceImpl;
import com.qx.chat.system.util.JsonUtil;
import com.qx.chat.system.util.SpringUtils;

import akka.actor.ActorRef;
import akka.actor.UntypedActor;

/**
 * UserActor负责用户的所有消息，事件的处理。 每一个在线用户会对应一个UserActor。
 * 
 * @author cyf
 * 
 */
public class UserActor extends UntypedActor {

	private static final Logger LOGGER = LoggerFactory.getLogger(UserActor.class);

	/**
	 * 当前用户开启的所有会话连接
	 */
	@SuppressWarnings("unused")
	private Map<String, WebSocketSession> sessions = new HashMap<String, WebSocketSession>();

	/**
	 * 当前用户对象
	 */
	private String loginName;

	private WebSocketSession session;

	public UserActor(String loginName, WebSocketSession session) {
		this.loginName = loginName;
		this.session = session;
	}

	/**
	 * 所有事件、消息处理
	 */
	@Override
	public void onReceive(Object message) throws Exception {
		Data<?> data = (Data<?>) message;
		// 事件
		if (data.getType().equals(Event.TYPE)) {
			JSONObject t = JsonUtil.objectToJsonObject(data.getData());
			String eventType = t.getString("type");
			// 连接打开通知登录事件
			if (eventType.equals(SessionOpen.TYPE)) {
				SessionOpen open = new SessionOpen();
				open.setOpen(true);
				sendMessage(Data.buildEventMessage(open));
			}
			// 登录事件
			if (eventType.equals(Login.TYPE)) {
				JSONObject o = JsonUtil.objectToJsonObject(data.getData());
				Login login = new Login(o.getString("loginName"), o.getString("password"));
				// 验证
				if (login.authentication()) {
					// 推送用户状态至全体在线
					User user = login.getUser();
					UserEvent.Status st = new UserEvent.Status(user.getId(), user.getLoginName(), 1);
					ActorRef sessionActor = Qxchat.getInstance().getSessionActor();
					sessionActor.tell(new SessionEvent.SessionAllOnlineMsg(loginName, Data.buildEventMessage(st)),
							sessionActor);
				}
				sendMessage(Data.buildEventMessage(login));
			}
			// 推送好友状态
			if (eventType.equals(Status.TYPE)) {
				// 真正发送
				sendMessage(Data.buildEventMessage((Event) data.getData()));
			}
			// 获取好友
			if (eventType.equals(Firends.TYPE)) {
				Firends firends = new Firends(loginName);
				firends.findAll();
				sendMessage(Data.buildEventMessage(firends));
			}
			// 创建或重命名分组
			if (eventType.equals(BandEditEvent.EDITTYPE)) {
				JSONObject o = JsonUtil.objectToJsonObject(data.getData());
				BandEditEvent be = new BandEditEvent(o.getString("loginName"), o.getString("bandId"),
						o.getString("bandName"), o.getString("memberLoginName"));
				be.createOrUpdate();
				sendMessage(Data.buildEventMessage(be));
			}
			// 分组添加成员事件
			if (eventType.equals(BandEditEvent.ADDMEMBERTYPE)) {
				JSONObject o = JsonUtil.objectToJsonObject(data.getData());
				BandEditEvent bam = new BandEditEvent(o.getString("loginName"), o.getString("bandId"),
						o.getString("bandName"), o.getString("memberLoginName"));
				bam.addMember();
				sendMessage(Data.buildEventMessage(bam));
			}
			// 分组删除事件
			if (eventType.equals(BandEditEvent.DELTYPE)) {
				JSONObject o = JsonUtil.objectToJsonObject(data.getData());
				BandEditEvent bam = new BandEditEvent(o.getString("loginName"), o.getString("bandId"),
						o.getString("bandName"), o.getString("memberLoginName"));
				bam.delBand();
				sendMessage(Data.buildEventMessage(bam));
			}
			// 分组删除成员事件
			if (eventType.equals(BandEditEvent.DELMEMBERTYPE)) {
				JSONObject o = JsonUtil.objectToJsonObject(data.getData());
				BandEditEvent bam = new BandEditEvent(o.getString("loginName"), o.getString("bandId"),
						o.getString("bandName"), o.getString("memberLoginName"));
				bam.delMember();
				sendMessage(Data.buildEventMessage(bam));
			}
			// 创建或重命名群组组
			if (eventType.equals(GroupEditEvent.EDITTYPE)) {
				JSONObject o = JsonUtil.objectToJsonObject(data.getData());
				GroupEditEvent be = new GroupEditEvent(o.getString("loginName"), o.getString("groupId"),
						o.getString("groupName"));
				be.createOrUpdate();
				sendMessage(Data.buildEventMessage(be));
			}
			// 收到消息让接收消息方推到客户端
		} else if (data.getType().equals(Message.TYPE)) {
			JSONObject t = JsonUtil.objectToJsonObject(data.getData());
			TextMessage msg = (TextMessage) JSONObject.toJavaObject(t, TextMessage.class);
			// 记录时间以服务为准，双方第一次显示以其本地时间为准。
			msg.setTime(new Date());
			ChatRecordService chatRecordService = SpringUtils.getBean(ChatRecordServiceImpl.class);
			// 存储聊天记录
			ChatMessageRecord record = chatRecordService.insertChatMessageRecord(msg, ChatMessageRecord.USERMSGRECORD);
			msg.setId(record.getId());
			// 获取对方actor
			ActorRef userActor = Qxchat.getInstance().getActorByLoginName(msg.getTo());
			// 通知对方
			userActor.tell(Data.buildSendTextMessage(msg), userActor);
			// 推送消息到客户端
		} else if (data.getType().equals(Message.SENDTYPE)) {
			JSONObject t = JsonUtil.objectToJsonObject(data.getData());
			TextMessage msg = (TextMessage) JSONObject.toJavaObject(t, TextMessage.class);
			// 真正发送
			sendMessage(Data.buildTextMessage(msg));
			// 收到群消息让接收消息方推到客户端
		} else if (data.getType().equals(Message.GROUPTYPE)) {
			JSONObject t = JsonUtil.objectToJsonObject(data.getData());
			TextMessage msg = (TextMessage) JSONObject.toJavaObject(t, TextMessage.class);
			// 记录时间以服务为准，双方第一次显示以其本地时间为准。
			msg.setTime(new Date());

			ChatRecordService chatRecordService = SpringUtils.getBean(ChatRecordServiceImpl.class);
			AbstractRepository<GroupUser> groupUserDao = SpringUtils.getBean(GroupUserDaoImpl.class);
			List<GroupUser> gulist = groupUserDao.findList("group.id", msg.getTo());
			for (Iterator<GroupUser> iterator = gulist.iterator(); iterator.hasNext();) {
				GroupUser groupUser = (GroupUser) iterator.next();
				String toUserLoginName = groupUser.getUser().getLoginName();
				if (!StringUtils.equals(toUserLoginName, msg.getFrom())) {
					// 存储聊天记录
					msg.setTo(toUserLoginName);// 为了存储设置上
					ChatMessageRecord record = chatRecordService.insertChatMessageRecord(msg,
							ChatMessageRecord.GROUPMSGRECORD);
					msg.setId(record.getId());
					// 获取对方actor
					ActorRef userActor = Qxchat.getInstance().getActorByLoginName(toUserLoginName);
					// 通知对方
					userActor.tell(Data.buildSendGroupTextMessage(msg), userActor);
				}
			}
			// 推送群消息到客户端
		} else if (data.getType().equals(Message.SENDGROUPTYPE)) {
			JSONObject t = JsonUtil.objectToJsonObject(data.getData());
			TextMessage msg = (TextMessage) JSONObject.toJavaObject(t, TextMessage.class);
			// 真正发送
			sendMessage(Data.buildGroupTextMessage(msg));
			// 更新消息为已读取
		} else if (data.getType().equals(Message.READMSG)) {
			JSONObject t = JsonUtil.objectToJsonObject(data.getData());
			TextMessage msg = (TextMessage) JSONObject.toJavaObject(t, TextMessage.class);
			AbstractRepository<ChatMessageRecord> chatRecordDao = SpringUtils.getBean(ChatRecordDaoImpl.class);
			// 存储聊天记录
			chatRecordDao.findAndModify(msg.getId(), new Update().set("isRead", 1));
			// 读取未读消息
		} else if (data.getType().equals(Message.NOREADMSG)) {
			JSONObject t = JsonUtil.objectToJsonObject(data.getData());
			TextMessage msg = (TextMessage) JSONObject.toJavaObject(t, TextMessage.class);
			AbstractRepository<ChatMessageRecord> chatRecordDao = SpringUtils.getBean(ChatRecordDaoImpl.class);
			AbstractRepository<User> userDao = SpringUtils.getBean(UserDaoImpl.class);
			List<ChatMessageRecord> ls = null;
			if (msg.getChatType() == ChatMessageRecord.USERMSGRECORD) {
				User from = userDao.findOne("loginName", msg.getFrom());
				User to = userDao.findOne("loginName", loginName);
				Criteria criteria = new Criteria().andOperator(Criteria.where("speakerUserId").is(from.getId()),
						Criteria.where("audienceUserId").is(to.getId()),
						Criteria.where("isRead").is(ChatMessageRecord.NOREAD));
				List<Order> orders = new ArrayList<Order>();
				orders.add(new Order(Sort.Direction.ASC, "occureTime"));
				ls = chatRecordDao.findList(criteria, orders);
				if (ls != null && ls.size() > 0) {
					for (Iterator<ChatMessageRecord> iterator = ls.iterator(); iterator.hasNext();) {
						ChatMessageRecord cmr = (ChatMessageRecord) iterator.next();
						// 获取对方actor
						ActorRef userActor = Qxchat.getInstance()
								.getActorByLoginName(cmr.getAudienceUser().getLoginName());
						// 通知对方
						userActor.tell(Data.buildSendTextMessage(cmr), userActor);
					}
				}
			} else if (msg.getChatType() == ChatMessageRecord.GROUPMSGRECORD) {
				User to = userDao.findOne("loginName", loginName);
				Criteria criteria = new Criteria().andOperator(Criteria.where("audienceGroupId").is(msg.getGroupId()),
						Criteria.where("audienceUserId").is(to.getId()),
						Criteria.where("isRead").is(ChatMessageRecord.NOREAD));
				List<Order> orders = new ArrayList<Order>();
				orders.add(new Order(Sort.Direction.ASC, "occureTime"));
				ls = chatRecordDao.findList(criteria, orders);
				if (ls != null && ls.size() > 0) {
					for (Iterator<ChatMessageRecord> iterator = ls.iterator(); iterator.hasNext();) {
						ChatMessageRecord cmr = (ChatMessageRecord) iterator.next();
						// 获取对方actor
						ActorRef userActor = Qxchat.getInstance()
								.getActorByLoginName(cmr.getAudienceUser().getLoginName());
						// 通知对方
						userActor.tell(Data.buildSendGroupTextMessage(cmr), userActor);
					}
				}
			}
		}
	}

	/**
	 * 发送消息到客户端
	 * 
	 * @param loginName
	 * @param empNo
	 * @param message
	 * @throws Exception
	 */
	private void sendMessage(Data<?> message) throws Exception {
		String msg = "" + JSONObject.toJSONString(message);
		try {
			session.sendMessage(new org.springframework.web.socket.TextMessage(msg));
		} catch (Exception e) {
			LOGGER.error("websocket sendMessage exception: " + loginName);
			LOGGER.error(e.getMessage(), e);
			// clients.remove(loginName);
		}
	}
}
